<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title></title>
    <!-- 这里可以添加CSS样式文件 -->
  </head>
  <body>
     <script type="importmap">
      {
        "imports": {
          "three": "./threejs/build/three.module.js",
          "three/addons/": "./threejs/examples/jsm/"
        }
      }
    </script>
    <script type="module">
      import * as THREE from "three";
      import { OrbitControls } from "three/addons/controls/OrbitControls.js";

      

      const scene = new THREE.Scene();

      const camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );

      camera.position.set(0, 40, 40);

      const renderer = new THREE.WebGLRenderer();

      renderer.setSize(window.innerWidth, window.innerHeight);

      new OrbitControls(camera, renderer.domElement);

      window.onresize = () => {
        renderer.setSize(window.innerWidth, window.innerHeight);

        camera.aspect = window.innerWidth / window.innerHeight;

        camera.updateProjectionMatrix();
      };

      document.body.appendChild(renderer.domElement);

      /* 顶点着色器 */
      const vertexs = `varying vec2 vUv;
void main() {
  vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
  vUv = uv;
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}`;

      /* 片元着色器 */
      const fragments = `
uniform float time;
uniform float opacity;
uniform vec3 color;
uniform float num;
uniform float hiz;
varying vec2 vUv;
void main() {
  vec4 fragColor = vec4(0.);
  float sin = sin((vUv.y - time * hiz) * 10. * num);
  float high = 0.92;
  float medium = 0.4;
  if (sin > high) {
    fragColor = vec4(mix(vec3(.8, 1., 1.), color, (1. - sin) / (1. - high)), 1.);
  } else if(sin > medium) {
    fragColor = vec4(color, mix(1., 0., 1.-(sin - medium) / (high - medium)));
  } else {
    fragColor = vec4(color, 0.);
  }
  vec3 fade = mix(color, vec3(0., 0., 0.), vUv.y);
  fragColor = mix(fragColor, vec4(fade, 1.), 0.85);
  gl_FragColor = vec4(fragColor.rgb, fragColor.a * opacity * (1. - vUv.y));
}`;

      // 自定义材质
      const material = new THREE.ShaderMaterial({
        uniforms: {
          time: {
            type: "pv2",
            value: 0,
          },
          color: {
            type: "uvs",
            value: new THREE.Color("#FF4127"),
          },
          opacity: {
            type: "pv2",
            value: 1.0,
          },
          num: {
            type: "pv2",
            value: 10,
          },
          hiz: {
            type: "pv2",
            value: 0.03,
          },
        },
        vertexShader: vertexs,
        fragmentShader: fragments,
        blending: THREE.AdditiveBlending,
        transparent: !0,
        depthWrite: !1,
        depthTest: !0,
        side: THREE.DoubleSide,
      });

      let c = [0, 0, 10, 0, 10, 10, 0, 10, 0, 0];

      let posArr = [];

      let uvrr = [];

      let h = 10; //围墙拉伸高度

      for (let i = 0; i < c.length - 2; i += 2) {
        // 矩形的三角形1
        posArr.push(
          c[i],
          c[i + 1],
          0,
          c[i + 2],
          c[i + 3],
          0,
          c[i + 2],
          c[i + 3],
          h
        );

        // 矩形的三角形2
        posArr.push(
          c[i],
          c[i + 1],
          0,
          c[i + 2],
          c[i + 3],
          h,
          c[i],
          c[i + 1],
          h
        );

        // 注意顺序问题，和顶点位置坐标对应
        uvrr.push(0, 0, 1, 0, 1, 1);

        uvrr.push(0, 0, 1, 1, 0, 1);
      }

      const geometry = new THREE.BufferGeometry(); //声明一个空几何体对象

      // 设置几何体attributes属性的位置position属性
      geometry.attributes.position = new THREE.BufferAttribute(
        new Float32Array(posArr),
        3
      );

      // 设置几何体attributes属性的位置uv属性
      geometry.attributes.uv = new THREE.BufferAttribute(
        new Float32Array(uvrr),
        2
      );

      geometry.computeVertexNormals();

      const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh

      scene.add(mesh);

      function animate() {
        requestAnimationFrame(animate);

        mesh.rotation.x += 0.01;

        mesh.rotation.y += 0.01;

        material.uniforms.time.value += 0.03;

        renderer.render(scene, camera);
      }

      animate();
    </script>
  </body>
</html>
